﻿#include "decoder.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <gbm.h>

#define WIDTH 1920
#define HEIGHT 1080

Decoder::Decoder(QObject *parent)
    : QObject{parent}
{

}

bool Decoder::start_a_gbm()
{
    /* 1) 打开 render 节点（更安全，不会影响桌面） */
    int drm_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
    if (drm_fd < 0) {
        perror("open /dev/dri/renderD128");
        return false;
    }

    /* 2) 创建 GBM device */
    struct gbm_device *gbm = gbm_create_device(drm_fd);
    if (!gbm) {
        fprintf(stderr, "gbm_create_device failed\n");
        close(drm_fd);
        return false;
    }

    /* 3) 分配一个 GBM buffer (linear) 并 mmap */
    struct gbm_bo *bo = gbm_bo_create(gbm, WIDTH, HEIGHT,
                                      GBM_FORMAT_XRGB8888,
                                      GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING);
    if (!bo) {
        fprintf(stderr, "gbm_bo_create failed\n");
        gbm_device_destroy(gbm);
        close(drm_fd);
        return false;
    }

    uint32_t stride = 0;
    void *map_data = NULL;
    void *map = gbm_bo_map(bo, 0, 0, WIDTH, HEIGHT,
                           GBM_BO_TRANSFER_WRITE, &stride, &map_data);
    if (!map) {
        fprintf(stderr, "gbm_bo_map failed\n");
        gbm_bo_destroy(bo);
        gbm_device_destroy(gbm);
        close(drm_fd);
        return false;
    }

    /* 填充一些像素（蓝色横向渐变），注意 GBM_FORMAT_XRGB8888 是 32-bit */
    for (int y = 0; y < HEIGHT; ++y) {
        uint32_t *row = (uint32_t *)((uint8_t *)map + y * stride);
        for (int x = 0; x < WIDTH; ++x) {
            uint8_t b = (uint8_t)(255 * x / WIDTH);
            uint8_t g = (uint8_t)(255 * y / HEIGHT);
            row[x] = (0xFF << 24) | (g << 8) | (b << 0); // 0xAARRGGBB -> XRGB: AA unused for X
        }
    }
    gbm_bo_unmap(bo, map_data);

    int dma_fd = gbm_bo_get_fd(bo);
    if (dma_fd < 0) {
        fprintf(stderr, "gbm_bo_get_fd failed or not available on this libgbm.\n"
                        "On such systems you must export prime handle to FD via drmPrimeHandleToFD.\n");
        gbm_bo_destroy(bo);
        gbm_device_destroy(gbm);
        close(drm_fd);
        return false;
    }

    FrameStruct frame;
//    frame.buffer = buffer;
    frame.fd = dma_fd;
//    frame.mpp_colour_space = mpp_frame_get_colorspace(source_frame);
//    frame.mpp_colour_range = mpp_frame_get_color_range(source_frame);
//    frame.mpp_colour_primaries = mpp_frame_get_color_primaries(source_frame);
    frame.width = WIDTH;
    frame.height = HEIGHT;
    frame.offset_x = 0;
    frame.offset_y = 0;
    frame.hor_stride = gbm_bo_get_stride(bo);
    frame.ver_stride = gbm_bo_get_height(bo);
    //g_warning("get frame success, stream data..., width:%u, height:%u, offset_x:%u, offset_y:%u, hor_stride:%u, ver_stride:%u\n",
    //       frame.width, frame.height, frame.offset_x, frame.offset_y, frame.hor_stride, frame.ver_stride);
//    mpp_frame_deinit(&source_frame);
    Q_EMIT frameReceived(frame);
    return true;
}
